package top.easyblog.web.controller;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import top.easyblog.common.enums.ArticleType;
import top.easyblog.common.util.CookieUtils;
import top.easyblog.common.util.NetWorkUtils;
import top.easyblog.common.util.RedisUtils;
import top.easyblog.core.dao.model.Article;
import top.easyblog.core.dao.model.ArticleCounter;
import top.easyblog.core.dao.model.Category;
import top.easyblog.core.dao.model.User;
import top.easyblog.core.service.*;
import top.easyblog.web.config.autoconfig.qiniu.QiNiuCloudService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executor;

/**
 * Controller层抽取出来公共代用的方法
 *
 * @author ：huangxin
 * @modified ：
 * @since ：2020/06/15 19:54
 */
@Slf4j
@Component
public abstract class BaseController {

    /**
     * 用户登录token
     */
    public static final String USER_LOGIN_TOKEN = "user_login_token";
    /**
     * 用户信息标记
     */
    protected static final String REMEMBER_ME_COOKIE = "REMEMBER-ME-COOKIE";

    /**
     * 用户登录信息最大保存时间（免登陆最大时间）:60天
     */
    protected static final int MAX_USER_LOGIN_STATUS_KEEP_TIME = 60 * 60 * 24 * 60;

    /**
     * 浏览器保存用户名，密码90天
     */
    protected static final int REMEMBER_ME_TIME = 60 * 60 * 24 * 90;
    /**
     * Redis数据库号
     */
    public static final RedisUtils.RedisDataBaseSelector REDIS_DB = RedisUtils.RedisDataBaseSelector.DB_1;
    @Autowired
    protected CategoryService categoryService;
    @Autowired
    protected ArticleService articleService;
    @Autowired
    protected CommentService commentService;
    @Autowired
    protected UserAttentionService userAttention;
    @Autowired
    protected UserService userService;
    @Autowired
    protected UserSignLogService userSigninLogService;
    @Autowired
    protected UserAccountService userAccountService;
    @Autowired
    protected UserEmailLogService userEmailLogService;
    @Autowired
    protected UserPhoneLogService userPhoneLogService;
    @Autowired
    protected QiNiuCloudService qiNiuCloudService;
    @Autowired
    protected RedisUtils redisUtil;
    @Autowired
    protected Executor executor;
    @Autowired
    protected HotWordService hotWordService;


    protected boolean isMobileDevice(HttpServletRequest request) {
        //检查用户的访问设备
        String userAgent = request.getHeader("User-Agent");
        return userAgent.contains("Android") || userAgent.contains("iPhone");
    }


    /***
     * 页面共享的数据
     * @param model    Model
     * @param userId   用户Id
     * @param articleType   文章类型
     */
    void getArticleUserInfo(Model model, int userId, String articleType) {
        try {
            //作者的所有允许显示的分类
            List<Category> lists = categoryService.getUserAllViableCategory(userId);
            //作者的所有归档
            List<ArticleCounter> archives = articleService.getUserAllArticleArchives(userId);
            //作者的最新文章5篇文章
            List<Article> newestArticles = articleService.getUserNewestArticles(userId, 5);
            //作者的原创文章数
            Article article = new Article();
            article.setArticleUser(userId);
            article.setArticleType(ArticleType.ORIGINAL.getArticleType());
            int originalArticle = articleService.countSelective(article);
            //作者指定类型的所有文章
            List<Article> articles = articleService.getUserArticles(userId, articleType);
            //关于我的文章的评论数
            int receiveCommentNum = commentService.getReceiveCommentNum(userId);
            //我的关注数
            int attentionNumOfMe = userAttention.countAttentionNumOfMe(userId);
            model.addAttribute("attentionNumOfMe", attentionNumOfMe);
            model.addAttribute("receiveCommentNum", receiveCommentNum);
            model.addAttribute("categories", lists);
            model.addAttribute("archives", archives);
            model.addAttribute("newestArticles", newestArticles);
            model.addAttribute("articles", articles);
            model.addAttribute("articleNum", articles.size());
            model.addAttribute("originalArticleNum", originalArticle);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }


    /**
     * 用户登录，生成一个会话Id，以会话id为key，用户信息为value，存放到Redis，同时将以用户id为key，用户登录时间戳为value
     * 这个键用户检查用户是否登录，如果Redis中存在对应用户的id，那就不能让用户重复登录
     *
     * @param request
     * @param response
     * @param user
     * @return token
     */
    protected String doLogin(HttpServletRequest request, HttpServletResponse response, User user) {
        //登陆token
        String token= UUID.randomUUID().toString().replaceAll("-","").concat(String.valueOf(System.currentTimeMillis()));
        //更新用户的
        boolean updateResult = CookieUtils.updateCookie(request, response, USER_LOGIN_TOKEN, token, MAX_USER_LOGIN_STATUS_KEEP_TIME);
        if(!updateResult){
            CookieUtils.setCookie(request,response,USER_LOGIN_TOKEN,token, MAX_USER_LOGIN_STATUS_KEEP_TIME);
        }
        //会话信息，如果没有主动退出60天有效
        redisUtil.set(token, JSONObject.toJSONString(user), MAX_USER_LOGIN_STATUS_KEEP_TIME, REDIS_DB);
        //用户登录的时候同时将用户的id放入Redis，防止用户重复登录
        redisUtil.set(String.valueOf(user.getUserId()), System.currentTimeMillis(), MAX_USER_LOGIN_STATUS_KEEP_TIME, REDIS_DB);
        return token;
    }

    /**
     * 跳转到用户登录前的页面
     *
     * @param request HttpServletRequest
     * @return java.lang.String
     */
    protected String loginRedirectUrl(HttpServletRequest request) {
        String ip = NetWorkUtils.getInternetIPAddress(request);
        String refererUrl = (String) redisUtil.get("Referer-" + ip, REDIS_DB);
        if (Objects.nonNull(refererUrl) && !"".equals(refererUrl)) {
            //在每次取登录界面的时候都会在Redis中记录登录之前访问的页面Referer，登录成功后删除对应的Referer
            redisUtil.delete(REDIS_DB, "Referer-" + ip);
            log.info("redirect to : {}", refererUrl);
            return "redirect:" + refererUrl;
        }
        log.info("redirect to : index");
        return "redirect:/";
    }


}
